﻿package com.everydayflash.pv3d {
	
   import flash.display.Bitmap;
   import flash.display.BitmapData;
   import flash.display.Sprite;
   import flash.geom.Point;
   import org.papervision3d.cameras.Camera3D;
   import org.papervision3d.core.geom.renderables.Vertex3D;
   import org.papervision3d.core.proto.MaterialObject3D;
   import org.papervision3d.materials.BitmapFileMaterial;
   import org.papervision3d.materials.ColorMaterial;
   import org.papervision3d.materials.WireframeMaterial;
   import org.papervision3d.objects.primitives.Plane;
   import org.papervision3d.render.BasicRenderEngine;
   import org.papervision3d.scenes.Scene3D;
   import org.papervision3d.view.Viewport3D;
   import flash.events.Event;
   import flash.events.MouseEvent;
   import flash.system.fscommand;
   
   import flash.display.StageScaleMode;
   import flash.display.StageQuality;
   import flash.display.StageAlign;
   import flash.display.BitmapDataChannel;

   public class PerlinCarpet extends Sprite {
	   
        private var viewport:Viewport3D;
        private var scene:Scene3D;
        private var camera:Camera3D;
        private var renderer:BasicRenderEngine;
		
		private var plane:Plane;
		private var angle:Number = 0;
		private var offset:Number = .5;
		
		private var perlin:BitmapData;
		private var seed:int = 8790;
		private var move:Number = 0;
		private var speed:Number = 30;
		
		private var size:int = 21;
		
		private var mats:Array;
		private var matPointer:int = 0;

        public function PerlinCarpet() {
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.quality = StageQuality.LOW;
			stage.align = StageAlign.TOP_LEFT;
			
			mats = new Array();
			mats.push(new BitmapFileMaterial("../assets/sea.jpg"));
			mats.push(new WireframeMaterial(0x0000dd));
			
            initPapervision3D();
			buildPlane();
			buildPerlin();
			
			addEventListener(Event.ENTER_FRAME, render);
			stage.addEventListener(MouseEvent.CLICK, swapMaterial);
        }
		
		private function swapMaterial(me:MouseEvent=null):void {
			plane.material = mats[matPointer];
			matPointer++;
			if (matPointer == mats.length) matPointer = 0;
		}
		
		private function buildPerlin():void {
			perlin = new BitmapData(size, size, false);
			perlinize();
		}

        private function initPapervision3D():void{
            viewport = new Viewport3D(stage.stageWidth, stage.stageHeight);
            addChild(viewport);
            scene = new Scene3D();
            camera = new Camera3D();
			camera.zoom = 16;
            renderer = new BasicRenderEngine();
		}
		
		private function buildPlane():void {
			plane = new Plane(null, 300, 300, size - 1, size - 1);
			swapMaterial();
			plane.z = 0;
			plane.rotationX = -60;
			plane.rotationY = -30;
			plane.y += 50;
			scene.addChild(plane);
		}

		private function perlinize(e:Event = null):void {
			var p:Point = new Point(move, 0);
			perlin.perlinNoise(size, size, 3, seed, false, true, BitmapDataChannel.RED, true, [p,p,p]);
			move += size/speed;
		}
		
		private function render(e:Event):void {
			perlinize();
			
			var vs:Array = plane.geometry.vertices;
			var vc:int = vs.length;

			for (var i:int = 0; i < vc; i++) {
				var px:int = i % size;
				var py:int = i / size;
				var v:Vertex3D = vs[i] as Vertex3D;
				var vzpos:Number = perlin.getPixel(px, py) & 0xff;
				v.z = (128 - vzpos) * (mouseX / stage.stageWidth);
			}

            renderer.renderScene(scene, camera, viewport);
        }
   }
}









